/// @author: cairuoyu
/// @homepage: http://cairuoyu.com
/// @github: https://github.com/cairuoyu/flutter_admin
/// @date: 2021/6/21
/// @version: 1.0
/// @description: 常用工具类

import 'dart:convert';
import 'dart:io';
import 'dart:math';
import 'dart:typed_data';
import 'package:flutter/services.dart';
import 'package:flutter_admin/models/odoo/purchase_quality_problem.dart';
import 'package:flutter_admin/pages/common/cry/utils/http_util.dart';
import 'package:path_provider/path_provider.dart';
import 'package:permission_handler/permission_handler.dart';

import './helper/save_file_mobile.dart'
    if (dart.library.html) './helper/save_file_web.dart';
import 'package:flutter_admin/pages/common/cry/cry.dart';
import 'package:flutter_admin/pages/common/cry/cry_dialog.dart';
import 'package:flutter/material.dart';
import 'package:flutter_admin/common/routes.dart';
import 'package:flutter_admin/constants/constant.dart';
import 'package:flutter_admin/constants/enum.dart';
import 'package:flutter_admin/data/data_icon.dart';
import 'package:flutter_admin/models/tab_page.dart';
import 'package:flutter_admin/pages/layout/layout_controller.dart';
import 'package:flutter_admin/utils/store_util.dart';
import 'package:get/get.dart';
import 'package:url_launcher/url_launcher.dart';
import 'package:collection/collection.dart';
import 'package:intl/intl.dart';
import 'package:syncfusion_flutter_xlsio/xlsio.dart' hide Column, Alignment;

import 'adaptive_util.dart';

class Utils {
  static fullscreenDialog(Widget widget) {
    return Navigator.push<void>(
      Cry.context,
      MaterialPageRoute(
        builder: (_) => widget,
        fullscreenDialog: true,
      ),
    );
  }

  static openTab(String name) {
    TabPage? tabPage = (Routes.defaultTabPage + Routes.otherTabPage)
        .firstWhereOrNull((element) => element.url == name);
    if (tabPage == null) {
      var menuList = StoreUtil.getMenuList();
      var menu = menuList.firstWhereOrNull((element) => element.url == name);
      if (menu == null) {
        return;
      }
      tabPage = menu.toTabPage();
    }

    List<TabPage?> openedTabPageList = StoreUtil.readOpenedTabPageList();
    StoreUtil.writeCurrentOpenedTabPageId(tabPage!.id);
    int index = openedTabPageList.indexWhere((note) => note!.id == tabPage!.id);
    if (index <= -1) {
      openedTabPageList.add(tabPage);
      StoreUtil.writeOpenedTabPageList(openedTabPageList);
    }
    LayoutController layoutController = Get.find();
    layoutController.update();
  }

  static closeTab(TabPage? tabPage) {
    List<TabPage?> openedTabPageList = StoreUtil.readOpenedTabPageList();
    int index = openedTabPageList.indexWhere((note) => note!.id == tabPage!.id);
    if (index <= 0) {
      return;
    }
    openedTabPageList.removeAt(index);
    StoreUtil.writeOpenedTabPageList(openedTabPageList);
    if (StoreUtil.readCurrentOpenedTabPageId() == tabPage!.id) {
      StoreUtil.writeCurrentOpenedTabPageId(openedTabPageList.last!.id);
    }
    LayoutController layoutController = Get.find();
    layoutController.update();
  }

  static closeAllTab() {
    StoreUtil.init();
    LayoutController layoutController = Get.find();
    layoutController.update();
  }

  static closeOtherTab(TabPage tabPage) {
    List<TabPage?> openedTabPageList = StoreUtil.readOpenedTabPageList();
    openedTabPageList.removeWhere((element) =>
        element!.id != tabPage.id && !Routes.defaultTabPage.contains(element));
    StoreUtil.writeCurrentOpenedTabPageId(tabPage.id);
    StoreUtil.writeOpenedTabPageList(openedTabPageList);
    LayoutController layoutController = Get.find();
    layoutController.update();
  }

  static closeAllToTheRightTab(TabPage tabPage) {
    List<TabPage?> openedTabPageList = StoreUtil.readOpenedTabPageList();
    int index = openedTabPageList.indexWhere((note) => note!.id == tabPage.id);
    openedTabPageList.removeWhere((element) =>
        openedTabPageList.indexOf(element) > index &&
        !Routes.defaultTabPage.contains(element));
    StoreUtil.writeCurrentOpenedTabPageId(tabPage.id);
    StoreUtil.writeOpenedTabPageList(openedTabPageList);
    LayoutController layoutController = Get.find();
    layoutController.update();
  }

  static closeAllToTheLeftTab(TabPage tabPage) {
    List<TabPage?> openedTabPageList = StoreUtil.readOpenedTabPageList();
    int index = openedTabPageList.indexWhere((note) => note!.id == tabPage.id);
    openedTabPageList.removeWhere((element) =>
        openedTabPageList.indexOf(element) < index &&
        !Routes.defaultTabPage.contains(element));
    StoreUtil.writeCurrentOpenedTabPageId(tabPage.id);
    StoreUtil.writeOpenedTabPageList(openedTabPageList);
    LayoutController layoutController = Get.find();
    layoutController.update();
  }

  static isLocalEn(BuildContext context) {
    return (Get.locale ?? Get.deviceLocale)!.languageCode == 'en';
  }

  static isMenuDisplayTypeDrawer(BuildContext context) {
    LayoutController layoutController = Get.find();

    if (!isDisplayDesktop(context)) {
      layoutController.menuDisplayType = MenuDisplayType.drawer;
    }
    return layoutController.menuDisplayType == MenuDisplayType.drawer;
  }

  static getThemeData(
      {Color? themeColor, String? fontFamily, bool isDark = false}) {
    if (fontFamily != null) {
      currentFontFamily = fontFamily;
    }
    if (themeColor == null) {
      themeColor = Get.theme.primaryColor;
    }
    return ThemeData(
      brightness: isDark ? Brightness.dark : Brightness.light,
      primaryColor: themeColor,
      iconTheme: IconThemeData(color: themeColor),
      floatingActionButtonTheme: FloatingActionButtonThemeData(
        backgroundColor: themeColor,
      ),
      buttonTheme: ButtonThemeData(buttonColor: themeColor),
      elevatedButtonTheme: ElevatedButtonThemeData(
          style: ButtonStyle(
              backgroundColor: MaterialStateProperty.all(themeColor))),
      fontFamily: currentFontFamily,
    );
  }

  static String currentFontFamily = "Roboto";

  static isLogin() {
    return StoreUtil.hasData(Constant.CLIENT);
  }

  static logout() {
    StoreUtil.cleanAll();
  }

  static launchURL(url) async {
    if (await canLaunch(url)) {
      await launch(url);
    } else {
      throw 'Could not launch $url';
    }
  }

  static toPortal(BuildContext context, String message, String buttonText,
      {String url = "http://www.cairuoyu.com/flutter_portal"}) {
    cryAlertWidget(
      context,
      Container(
        height: 100,
        child: Column(
          children: [
            Text(message),
            SizedBox(
              height: 20,
            ),
            ElevatedButton(
              child: Text(buttonText),
              onPressed: () {
                Utils.launchURL(url);
              },
            ),
          ],
        ),
      ),
    );
  }

  static toIconData(String? icon) {
    if (icon == null || icon == '') {
      return Icons.menu;
    }
    // IconData iconData = IconData(int.parse(icon), fontFamily: 'MaterialIcons');
    return iconMap[icon] ?? Icons.menu;
  }

  static timeUTC(utcTime, {bool isToBeijing = true}) {
    DateTime beijingTime;
    if (isToBeijing) {
      beijingTime = DateTime.parse("${utcTime.substring(0, 19)}-0800");
    } else {
      beijingTime = DateTime.parse("${utcTime.substring(0, 19)}+0800");
    }
    return DateFormat('yyyy-MM-dd HH:mm:ss').format(beijingTime);
  }

  static String getDate({String? date}) {
    DateTime time = DateTime.now();
    if (date != null) {
      time = DateTime.parse(date);
    }
    return DateFormat('yyyy-MM-dd').format(time);
  }

  /**
   * 导出Excel
   * 这里需要注意model的tomap方法
   */

  static void generateExcel(
      {String? fileName, List<Map>? configure, List? data}) async {
    // Create a new Excel Document.
    final Workbook workbook = Workbook();

    // Accessing sheet via index.
    final Worksheet sheet = workbook.worksheets[0];
    sheet.enableSheetCalculations();

    // 标题
    List titleList = [];
    for (var i = 0; i < configure!.length; i++) {
      var title = configure[i];
      sheet.getRangeByIndex(1, i + 1).columnWidth = title["columnWidth"];
      sheet.getRangeByIndex(1, i + 1).rowHeight = 20;
      titleList.add(title["label"]);
    }
    // 添加标题
    sheet.importList(titleList, 1, 1, false);

    for (var i = 0; i < data!.length; i++) {
      var text = data[i].toMap();
      // 正文
      var textList = [];
      for (var j = 0; j < configure.length; j++) {
        var title = configure[j];
        sheet.getRangeByIndex(i + 1, j + 1).columnWidth = title["columnWidth"];
        sheet.getRangeByIndex(i + 1, j + 1).rowHeight = 20;
        textList.add(text[title["name"]]);
      }
      // 添加正文
      sheet.importList(textList, 2 + i, 1, false);
    }

    //Import the Object list to Sheet
    // sheet.importList(list, 2, firstColumn, isVertical);
    //Defining a global style with properties.
    final Style globalStyle = workbook.styles.add('globalStyle');
    globalStyle.fontName = 'Times New Roman';
    globalStyle.fontSize = 14;
    globalStyle.backColorRgb = Color.fromARGB(128, 242, 242, 242);
    globalStyle.bold = true;
    globalStyle.wrapText = false;
    globalStyle.hAlign = HAlignType.center;
    globalStyle.vAlign = VAlignType.center;

    final Style globalStyle1 = workbook.styles.add('globalStyle1');
    globalStyle1.fontName = 'Times New Roman';
    globalStyle1.fontSize = 12;
    globalStyle1.wrapText = false;
    globalStyle1.hAlign = HAlignType.center;
    globalStyle1.vAlign = VAlignType.center;

    var char = intToASCII(96 + configure.length);
    //Apply GlobalStyle
    sheet.getRangeByName('A1:' + char + '1').cellStyle = globalStyle;

    //Apply GlobalStyle1
    sheet
        .getRangeByName('A2:' + char + (data.length + 1).toString())
        .cellStyle = globalStyle1;
    // Save and dispose workbook.
    final List<int>? bytes = workbook.saveAsStream();
    workbook.dispose();
    // Download the output file in web.
    await FileSaveHelper.saveAndLaunchFile(bytes!, '$fileName.xlsx');
  }

  static Future<void> generateTemplateExcel(
      String fileName, PurchaseQualityProblem problem) async {
    /**
     * 
     * 通过代码生成指定模板的表格 
     * 
     * @Author: chendeji
     * @Date: 2022-05-18 12:17:42
    */

    // 先读取图片，然后插入图片
// Create a new Excel document.
    final Workbook workbook = new Workbook();
//Accessing worksheet via index.
    final Worksheet sheet = workbook.worksheets[0];

    //Defining a global style with all properties.
    Style a1Style = workbook.styles.add('style');
    a1Style.hAlign = HAlignType.center;
    a1Style.vAlign = VAlignType.center;
    a1Style.fontSize = 20;
    a1Style.bold = true;
    a1Style.borders.top.lineStyle = LineStyle.thin;
    a1Style.borders.left.lineStyle = LineStyle.thin;
    a1Style.borders.right.lineStyle = LineStyle.thin;
    a1Style.borders.all.color = '#000000';

    Style normal = workbook.styles.add('style1');
    normal.hAlign = HAlignType.right;
    normal.vAlign = VAlignType.center;
    normal.borders.left.lineStyle = LineStyle.thin;
    normal.borders.right.lineStyle = LineStyle.thin;
    normal.borders.all.color = '#000000';
    normal.fontSize = 12;

    Style normal1 = workbook.styles.add('style2');
    normal1.hAlign = HAlignType.left;
    normal1.vAlign = VAlignType.center;
    normal1.borders.all.lineStyle = LineStyle.thin;
    normal1.borders.all.color = '#000000';
    normal1.wrapText = true;
    normal1.fontSize = 12;

    // 加载顶部左上角图片
    ByteData data = await rootBundle.load('assets/template/excel_image.png');
    final List<int> bytes =
        data.buffer.asUint8List(data.offsetInBytes, data.lengthInBytes);
    // final List<int> bytes = File('image.png').readAsBytesSync();
    final Picture picture = sheet.pictures.addStream(1, 1, bytes);
    picture.width = 158;
    picture.height = 57;

    // 制作第一行单元格，合并A1-D1 宽：
    sheet.getRangeByName('A1:D1')
      ..merge()
      ..cellStyle = a1Style
      ..rowHeight = 29
      ..columnWidth = 24
      ..text = '原材料质量反馈报告';
    // 制作第一行单元格，合并A2-D2 宽：
    sheet.getRangeByName('A2:D2')
      ..merge()
      ..cellStyle = normal
      ..rowHeight = 20
      ..columnWidth = 24
      ..text = ' 编号：KD04-JC-0001';

    void fileData(int row, List<String> title, List<String> value) {
      sheet.getRangeByName('A$row')
        ..text = title[0]
        ..cellStyle = normal1
        ..columnWidth = 15
        ..rowHeight = 24;
      sheet.getRangeByName('B$row')
        ..text = value[0]
        ..cellStyle = normal1
        ..columnWidth = 33
        ..rowHeight = 24;
      sheet.getRangeByName('C$row')
        ..text = title[1]
        ..cellStyle = normal1
        ..columnWidth = 15
        ..rowHeight = 24;
      sheet.getRangeByName('D$row')
        ..text = value[1]
        ..cellStyle = normal1
        ..columnWidth = 33
        ..rowHeight = 24;
    }

    var inputData = [
      [
        ['流水号', '供应单位'],
        [problem.serialnumber.toString(), problem.supplierName.toString()]
      ],
      [
        ['型号规格', '产品名称'],
        [problem.spec.toString(), problem.productName.toString()]
      ],
      [
        ['检测时间', '来料数量'],
        [problem.jcrq.toString(), problem.instockqty.toString()]
      ],
      [
        ['抽样数量', '不合格数量'],
        [problem.checkqty.toString(), problem.unqualifiedqty.toString()]
      ]
    ];

    for (var i = 3; i < 7; i++) {
      fileData(i, inputData[i - 3][0], inputData[i - 3][1]);
    }

    void fileData2(int row, String key, String value) {
      sheet.getRangeByName('A${row + 7}')
        ..text = key
        ..cellStyle = normal1
        ..rowHeight = 50;

      sheet.getRangeByName('B${row + 7}:D${row + 7}')
        ..merge()
        ..text = value
        ..cellStyle = normal1
        ..rowHeight = 50;
    }

    var ccCaurse = problem.causeanalysis.toString().split('-')[0];
    var lcCaurse = problem.causeanalysis.toString().split('-')[1];
    var ccSolution = problem.rectificationmeasures.toString().split('-')[0];
    var lcSolution = problem.rectificationmeasures.toString().split('-')[1];

    var inputData2 = [
      ['问题描述', problem.questiondescription.toString()],
      ['处理方式', problem.zlbpsyj.toString()],
      /**
       * 
       * 原因分析，需要拆分开来，变成产出原因，和流出原因
       * 改进措施，需要拆分为产出改进措施，流出改进措施 
       * @Author: chendeji
       * @Date: 2022-05-25 11:06:18
      */
      ['供应商原因分析', '产出原因：$ccCaurse \n\n 流出原因：$lcCaurse'],
      ['改进措施', '产出原因改进措施：$ccSolution \n\n 流出原因改进措施：$lcSolution'],
      ['跟踪情况验证（中天宽带技术有限公司填写）', problem.effectiveverification.toString()],
    ];

    for (var i = 0; i < 5; i++) {
      fileData2(i, inputData2[i][0], inputData2[i][1]);
    }

// Save the document.
    final List<int> exbytes = workbook.saveAsStream();
//Dispose the workbook.
    workbook.dispose();
    // Download the output file in web.
    await FileSaveHelper.saveAndLaunchFile(exbytes, '$fileName.xlsx');
  }

  static dynamic intToASCII(int figure) {
    var listInt = [figure];
    var int2utf8 = Uint8List.fromList(listInt);
    return Utf8Codec().decode(int2utf8);
  }

  static Uint8List encode(String s) {
    var encodedString = utf8.encode(s);
    var encodedLength = encodedString.length;
    var data = ByteData(encodedLength + 4);
    data.setUint32(0, encodedLength, Endian.big);
    var bytes = data.buffer.asUint8List();
    bytes.setRange(4, encodedLength + 4, encodedString);
    return bytes;
  }

  static const MethodChannel _channel =
      const MethodChannel('install_apk_plugin');

  static Future<bool> installApk(String path) async {
    final bool isSuccess = await _channel.invokeMethod('installApk', path);
    return isSuccess;
  }

  /**
   * 更新文件
   */
  static void showUpdateDialog(
      BuildContext context, title, content, String url) {
    bool isDownload = false;
    double progress = 0;

    showDialog(
      context: context,
      barrierDismissible: false,
      builder: (context) =>
          new StatefulBuilder(builder: (context, StateSetter setState) {
        List<Widget> contentWidget = [];
        List<Widget> actionWidget = [];
        contentWidget.add(Text(content));
        contentWidget.add(SizedBox(
          height: 10.0,
        ));

        if (isDownload) {
          contentWidget.add(LinearProgressIndicator(
            value: progress,
            backgroundColor: Colors.black,
          ));
        } else {
          actionWidget = [
            FlatButton(
              child: Text(
                "取消",
                style: TextStyle(
                  fontFamily: "Montserrat",
                  color: Color(0xFF8C939F),
                  fontSize: 14.0,
                ),
              ),
              onPressed: () {
                Navigator.of(context).pop();
              },
            ),
            FlatButton(
              child: Text(
                "更新",
                style: TextStyle(
                  fontFamily: "Montserrat",
                  color: Color(0xFF081530),
                  fontSize: 14.0,
                ),
              ),
              onPressed: () {
                if (url != null && url.contains('.apk')) {
                  _getLocalPath().then((appDir) {
                    if (appDir == null) {
                      return;
                    }
                    setState(() {
                      isDownload = true;
                    });
                    String path = appDir.path + title + ".apk";
                    HttpUtil.download(url, path, (received, total) {
                      setState(() {
                        progress = received / total;
                        if (progress == 1) {
                          Navigator.of(context).pop();
                          installApk(path);
                        } else {
                          isDownload = true;
                        }
                      });
                    });
                  });
                }
              },
            ),
          ];
        }

        return new AlertDialog(
          title: Text(title),
          content: SingleChildScrollView(
            child: ListBody(
              children: contentWidget,
            ),
          ),
          actions: actionWidget,
        );
      }),
    );
  }

  /**
   * 获取本地存储路径
   */
  static _getLocalPath() async {
    var status = await Permission.storage.status;
    if (status != PermissionStatus.granted) {
      if (await Permission.contacts.request().isGranted) {
        return null;
      }
    }

    Directory appDir;
    if (Platform.isIOS) {
      appDir = await getApplicationDocumentsDirectory();
    } else {
      appDir = (await getExternalStorageDirectory())!;
    }
    String appDocPath = appDir.path + "/opengit_flutter";
    Directory appPath = Directory(appDocPath);
    await appPath.create(recursive: true);
    return appPath;
  }

  /**
   * 校验版本号
   */
  static int compareVersion(String localVersion, String serverVersion) {
    if (localVersion == serverVersion) {
      return 0;
    }
    List<String> version1Array = localVersion.split(".");
    List<String> version2Array = serverVersion.split(".");
    int index = 0;
    // 获取最小长度值
    int minLen = min(version1Array.length, version2Array.length);
    int diff = 0;
    // 循环判断每位的大小
    while (index < minLen &&
        (diff = int.parse(version1Array[index]) -
                int.parse(version2Array[index])) ==
            0) {
      index++;
    }
    if (diff == 0) {
      // 如果位数不一致，比较多余位数
      for (int i = index; i < version1Array.length; i++) {
        if (int.parse(version1Array[i]) > 0) {
          return 1;
        }
      }

      for (int i = index; i < version2Array.length; i++) {
        if (int.parse(version2Array[i]) > 0) {
          return -1;
        }
      }
      return 0;
    } else {
      return diff > 0 ? 1 : -1;
    }
  }
// static bool isCurrentOpenedMenu(List<TreeVO<Menu>> data) {
//   for (var treeVO in data) {
//     if (treeVO.children != null && treeVO.children.length > 0) {
//       return isCurrentOpenedMenu(treeVO.children);
//     }
//     return StoreUtil.readCurrentOpenedTabPageId() == treeVO.data.id;
//   }
//   return false;
// }
}
